import 'dart:io';
import 'dart:typed_data';

import 'package:dio/dio.dart';
import 'package:www.znpigai.teacher/global_store/state.dart';

class HttpResult {
  bool success;
  int code;
  String errorMsg;
  dynamic data;
}

class Http {
  static var _dio = new Dio();

  static void init() {
    _dio.options.connectTimeout = 10000; //10s
    _dio.options.receiveTimeout = 10000;
//  dio.options.validateStatus = (int status) {
//    return status > 0;
//  };
//    _dio.options.contentType =
//        ContentType.parse("application/x-www-form-urlencoded");
    _dio.options.headers = {
      HttpHeaders.userAgentHeader: 'iOS Student',
      'ticket': GlobalState.ticket,
    };
    _dio.interceptors.add(LogInterceptor(
        requestBody: GlobalState.isInDebugMode,
        responseBody: GlobalState.isInDebugMode)); //开启请求日志
  }

  static Future<HttpResult> get(String url,
      {Map<String, dynamic> query}) async {
    await Future.delayed(Duration(milliseconds: DateTime.now().month * 500));

    if (url.startsWith('/')) {
      url = GlobalState.baseUrl(url);
    }

    HttpResult result = new HttpResult();
    try {
      var response = await _dio.get(url, queryParameters: query);
      result = successResult(response);
    } on DioError catch (e) {
      result = failResult('GET', e);
    }
    return result;
  }

  static Future<HttpResult> post(String url,
      {Map<String, dynamic> data,
      Map<String, dynamic> query,
      bool isJson = false}) async {
    if (url.startsWith('/')) {
      url = GlobalState.baseUrl(url);
    }

    String type = 'application/x-www-form-urlencoded';
    if (isJson) {
      type = 'application/json';
    }

    HttpResult result = new HttpResult();
    try {
      var response = await _dio.post(url,
          data: data,
          queryParameters: query,
          options: new Options(contentType: ContentType.parse(type)));
      result = successResult(response);
    } on DioError catch (e) {
      result = failResult('POST', e);
    }

    return result;
  }

  static Future<HttpResult> upload(String url,
      {String filePath,
      Map<String, dynamic> query,
      Map<String, dynamic> headers}) async {
    assert(filePath != null);
    if (url.startsWith('/')) {
      url = GlobalState.baseUrl(url);
    }

    if (headers == null) {
      headers = {};
    }

    HttpResult result = new HttpResult();

    try {
      var file = new File(filePath);
      var info = new UploadFileInfo(file, filePath);
      Map<String, String> fileHeaders = {
        HttpHeaders.contentLengthHeader: file.lengthSync().toString(),
        HttpHeaders.contentTypeHeader: info.contentType.toString(),
      };
      headers.addAll(fileHeaders);

      var response = await _dio.post(url,
          queryParameters: query,
          options: new Options(
            headers: headers,
          ),
          data: file.openRead());
      result = successResult(response);
    } on DioError catch (e) {
      result = failResult('POST', e);
    }

    return result;
  }

  static Future<HttpResult> uploadPhoto(String url,
      {Uint8List photoBuffer,
      Map<String, dynamic> query,
      Map<String, dynamic> headers}) async {
    assert(photoBuffer != null);
    if (url.startsWith('/')) {
      url = GlobalState.baseUrl(url);
    }

    if (headers == null) {
      headers = {};
    }

    HttpResult result = new HttpResult();

    try {
      FormData formData = new FormData.from({
        "file": new UploadFileInfo.fromBytes(photoBuffer, "tmpPhoto.jpg"),
      });

      var response = await _dio.post(
        url,
        queryParameters: query,
        options: new Options(
          contentType: ContentType.parse("application/x-www-form-urlencoded"),
          headers: headers,
        ),
        data: formData,
      );
      result = successResult(response);
    } on DioError catch (e) {
      result = failResult('POST', e);
    }

    return result;
  }

  static HttpResult successResult(var response) {
    int code = response.data['code'];
    HttpResult result = new HttpResult()..code = code;

    if (code == 200) {
      // ok
      result.success = true;
      result.data = response.data['entity'];
    } else if (code == null && response.data['result'] != null) {
      result.success = true;
      result.data = response.data['result'];
    } else {
      // bad
      result.success = false;
      result.errorMsg = response.data['msg'];
    }

    return result;
  }

  static HttpResult failResult(String method, DioError e) {
    HttpResult result = new HttpResult();
    result.success = false;
    if (e.response != null) {
      result.code = e.response.statusCode;
      result.errorMsg = e.response.data['msg'];
    } else {
      result.code = 99999;
      result.errorMsg = e.message;
    }
    return result;
  }

  static Future rawGet(String url, {Map<String, dynamic> query}) async {
    var response = await _dio.get(url, queryParameters: query);
    return response;
  }

  static Future rawPost(String url,
      {Map<String, dynamic> fields, Map<String, dynamic> query}) async {
    var response = await _dio.post(url, data: fields, queryParameters: query);
    return response.data;
  }
}
